<!-- 文章编辑器 -->
<template>
  <div class="grid max-w-screen">
    <!-- 网站 logo -->
    <div class="col-2 text-center">
      <Image style="cursor: pointer;"
             alt="网站图标"
             src="https://img.yeziji.xyz/mobile/logger/forum-mobile.png"
             :width="140"
             @click="toHome()"/>
    </div>
    <!-- 头部用户按钮 -->
    <div class="col-10 align-self-center flex align-items-center" style="justify-content: right !important;">
      <UserButton/>
    </div>
    <!-- 标题输入框 -->
    <div class="col-12">
      <div class="p-inputgroup p-2">
        <span class="p-inputgroup-addon required-field">标题</span>
        <InputText placeholder="输入文章标题" v-model="publishEntity.title"/>
      </div>
    </div>
    <!-- 专栏选择框 -->
    <div class="col-6">
      <ChipsSelected class="p-2"
                     addon="专栏"
                     filter
                     key="specialsChipsSelected"
                     :max="1"
                     :items="specials"
                     :default-selected="detailUpdateValues.special"
                     @change="specialsChangeHandler"/>
    </div>
    <!-- 标签选择框 -->
    <div class="col-6">
      <ChipsSelected class="p-2"
                     addon="标签"
                     customer-addon-class="required-field"
                     filter
                     key="tagsChipsSelected"
                     :max="5"
                     :items="tags"
                     :default-selected="detailUpdateValues.tags"
                     @change="tagsChangeHandler"/>
    </div>
    <!-- 文章简介 -->
    <div class="col-12">
      <div class="p-inputgroup p-2">
        <span class="p-inputgroup-addon required-field">简介</span>
        <Textarea style="height: 10vh; width: calc(100vw - 1.5rem); resize: none"
                  v-model="publishEntity.desc"
                  placeholder="输入文章简介"/>
      </div>
    </div>
    <!-- 编辑器 -->
    <div class="col-12">
      <div class="p-2 flex align-items-center justify-content-center">
        <VditorEditor :height="'calc(100vh - 1.5rem)'"
                      :width="'100vw'"
                      :add-toolbar="customerToolbar"
                      :editor-value="detailUpdateValues.content"
                      @change="vditorEditorChangeHandler"/>
      </div>
    </div>
  </div>

  <!-- 用户文章 sidebar -->
  <Sidebar v-model:visible="detailSidebarVisible"
           position="top"
           style="height: 80vh;"
           :baseZIndex="10000">
    <template #header>
      <div class="grid text-center w-screen">
        <div class="col-12">
          用户个人文章中心
        </div>
        <div class="col-12">
          <span class="p-inputgroup"
                style="text-align: center; display: block;">
            <InputText style="text-align: center;width: 50vw;"
                       type="text"
                       v-model="detailFilterInfo.title"
                       placeholder="搜索文章标题"/>
            <Button icon="pi pi-search" class="p-button-warning" @click="detailSearch"/>
          </span>
          <!-- 筛选是否发布 -->
          <SelectButton v-model="detailFilterInfo.published"
                        class="mt-2"
                        optionLabel="name"
                        optionValue="value"
                        aria-labelledby="published"
                        :options="[{name: '未发布', value: 1}, {name: '已发布', value: 0}]"/>
        </div>
        <div class="col-6">
          <!-- 筛选专栏 -->
          <SelectButton v-model="detailFilterInfo.special"
                        :options="specials"
                        aria-labelledby="special"/>
        </div>
        <div class="col-6">
          <!-- 筛选标签 -->
          <SelectButton v-model="detailFilterInfo.tags"
                        :options="tags"
                        aria-labelledby="special"/>
        </div>
      </div>
    </template>
    <div id="userDetail" :ref="userDetailRef" class="grid">
      <div class="col-12">
        <DataTable id="userDetailTable"
                   v-model:selection="userDetailSelected"
                   selectionMode="single"
                   dataKey="id"
                   responsiveLayout="scroll"
                   :value="userDetails"
                   :rowHover="true">
          <Column field="title" header="标题" headerClass="m-table-th" bodyStyle="text-align: center;">
            <template #body="slotProps">
              <h3>{{ slotProps.data.title }}</h3>
            </template>
          </Column>

          <Column field="tags" header="标签" headerClass="m-table-th" bodyStyle="text-align: center;">
            <template #body="slotProps">
              <Tag v-show="slotProps.data.tags && slotProps.data.tags !== ''"
                   v-for="(item, index) of slotProps.data.tags.split(',')"
                   :key="index">
                {{ item }}
              </Tag>
            </template>
          </Column>
          <Column field="special" header="专栏" headerClass="m-table-th" bodyStyle="text-align: center;">
            <template #body="slotProps">
              <Tag v-show="slotProps.data.special && slotProps.data.special !== ''"
                   severity="success">
                {{ slotProps.data.special }}
              </Tag>
            </template>
          </Column>
          <Column field="tempSave"
                  header="发布状态"
                  headerClass="m-table-th"
                  bodyStyle="text-align: center;">
            <template #body="slotProps">
              <strong :style="{color: slotProps.data.tempSave ? 'blue' :'red'}">
                {{ slotProps.data.tempSave ? '未发布' : '已发布' }}
              </strong>
            </template>
          </Column>
          <Column field="publishTime" header="最后编写时间" headerClass="m-table-th" bodyStyle="text-align: center;">
            <template #body="slotProps">
              <h4>{{ slotProps.data.publishTime }}</h4>
            </template>
          </Column>
          <Column field="opera"
                  header="操作"
                  bodyStyle="text-align: center;"
                  headerClass="m-table-th">
            <template #body="slotProrps">
              <Button @click="editDetail(slotProrps.data.id, slotProrps.data.tempSave)"
                      icon="pi pi-file-edit"
                      class="p-button-success p-button-sm m-1 m-btn-jz"
                      type="button"
                      label="编辑"/>

              <Button @click="saveDetail(0, slotProrps.data.id, slotProrps.data.tempSave)"
                      :icon="`pi ${slotProrps.data.tempSave ? 'pi-file-export' : 'pi-file-import'}`"
                      :label="slotProrps.data.tempSave ? '发布' : '暂存'"
                      type="button"
                      :class="`p-button-success p-button-sm m-1 ${slotProrps.data.tempSave ? 'm-btn-p-1' : 'm-btn-gr-2'}`"/>

              <Button @click="deleteDetail(0, slotProrps.data.id, slotProrps.data.tempSave)" icon="pi pi-trash"
                      class="p-button-success p-button-sm m-1 m-btn-red-1"
                      type="button"
                      label="删除"/>
            </template>
          </Column>
          <!-- 加载 -->
          <template #footer v-if="userDetailsLoading">
            <div class="text-center">
              <ProgressSpinner/>
            </div>
          </template>
          <template v-if="!userDetailsLoading" #empty>
            <div class="text-center">
              没有数据
            </div>
          </template>
        </DataTable>
      </div>
    </div>
  </Sidebar>
  <!-- 发布文章时，或手动设置弹出需要补充的信息框 -->
  <Dialog header="温馨提示" v-model:visible="operaConfirmationVisible" :style="{width: '680px'}" :modal="true">
    <div class="confirmation-content">
      <i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem"/>
      <span>{{ operaConfirmationMsg }}</span>
    </div>
    <template #footer>
      <Button :label="cancelOperaInfo" icon="pi pi-times" @click="operaConfirmationCancelHandler(operaMode)"
              class="p-button-text"/>

      <Button v-show="(operaMode===3 || operaMode === 2) && publishEntity.id !== 0"
              label="清除数据并创建新文章"
              icon="pi pi-times"
              @click="operaConfirmationSubmitHandler(4)"
              class="p-button-text"/>

      <Button :label="submitOperaInfo" icon="pi pi-check" @click="operaConfirmationSubmitHandler(operaMode)"
              class="p-button-text" autofocus/>
    </template>
  </Dialog>
</template>
<script setup lang="ts">
/** JS */
import {nextTick, onMounted, reactive, Ref, ref, watch} from 'vue';
import {DetailPageInfo, DetailPublish, DetailResponseData} from '@/interface/detail/entity/DetailEntityInterface';
import {DetailService, ResponseResult, SpecialService, TagService, MarkdownService} from '@/utils/ApiRequest';
import {useRoute, useRouter} from 'vue-router';
import {encrypt, decrypt} from '@/utils/PakoUtils';
import toast from '@/utils/Toast';
import {ScrollHandlerInfo, scrollHandler} from '@/utils/ScrollEndHandler';

/** 组件 */
import Tag from 'primevue/tag';
import VditorEditor from '@/components/editor/VditorEditor.vue';
import ChipsSelected from '@/components/input/ChipsSelected.vue';
import UserButton from '@/components/button/UserButton.vue';
import Textarea from 'primevue/textarea';
import Sidebar from 'primevue/sidebar';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import ProgressSpinner from 'primevue/progressspinner';
import SelectButton from 'primevue/selectbutton';
import Dialog from 'primevue/dialog';

const detailService = new DetailService(),
    tagService = new TagService(),
    specialService = new SpecialService(),
    markdownService = new MarkdownService();
const router = useRouter(), route = useRoute();

/** 自定义 toolbar */
const customerToolbar = [
  "|",
  {
    hotkey: '⌥⌘R',
    name: 'refresh',
    icon: '<svg t="1671688181901" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11842" width="32" height="32"><path d="M512 919.552c-224.768 0-407.552-182.784-407.552-407.552 0-8.704 0.512-17.408 1.024-26.112l71.68 4.608c-0.512 7.168-0.512 14.336-0.512 21.504 0 185.344 150.528 335.872 335.872 335.872 86.528 0 168.448-32.768 230.912-92.16l49.152 52.224c-76.288 72.192-175.616 111.616-280.576 111.616zM919.552 512h-71.68c0-11.776-0.512-23.552-2.048-35.328-17.92-171.52-161.28-300.544-334.336-300.544-67.584 0-132.096 19.968-187.904 57.344L284.16 174.08C351.232 128.512 430.08 104.448 512 104.448c209.408 0 384 156.672 405.504 365.056 1.536 13.824 2.048 28.16 2.048 42.496z" p-id="11843"></path><path d="M140.288 290.816L28.16 491.52c-3.072 5.12 1.024 11.776 6.656 11.776h223.744c6.144 0 9.728-6.144 6.656-11.776L153.6 290.816c-3.072-5.632-10.752-5.632-13.312 0zM870.4 675.84l-112.128-200.704c-3.072-5.12 1.024-11.776 6.656-11.776h223.744c6.144 0 9.728 6.144 6.656 11.776L883.712 675.84c-2.56 5.12-10.24 5.12-13.312 0z" p-id="11844"></path><path d="M270.336 202.24a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" p-id="11845"></path><path d="M728.576 784.896a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" p-id="11846"></path></svg>',
    tip: '刷新重置',
    className: 'details',
    tipPosition: 'n',
    click: () => refresh()
  },
  {
    hotkey: '⌥⌘L',
    name: 'details',
    icon: '<svg t="1659665172911" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3820" width="128" height="128"><path d="M211.65579378 428.36514133l331.56361481-1.89326222 0.44297482 77.6722963-331.56361482 1.89326222zM211.71162075 605.93129245l252.67768888-1.89326223 0.58254222 77.6722963-252.67768888 1.89326223zM211.82084741 251.12788385l561.54642962-2.53648593 0.3519526 77.6722963-561.54642963 2.53648593z" p-id="3821"></path><path d="M471.10068148 998.30139259H117.8130963c-21.48124445 0-38.83614815-17.3549037-38.83614815-38.83614814V88.80734815c0-21.48124445 17.3549037-38.83614815 38.83614815-38.83614815h783.64065185c21.48124445 0 38.83614815 17.3549037 38.83614815 38.83614815v430.2317037c0 21.48124445-17.3549037 38.83614815-38.83614815 38.83614815s-38.83614815-17.3549037-38.83614815-38.83614815V127.6434963H156.64924445v792.86423703h314.45143703c21.48124445 0 38.83614815 17.3549037 38.83614815 38.83614815s-17.3549037 38.95751111-38.83614815 38.95751111z" p-id="3822"></path><path d="M715.76841482 939.07626667c-112.62482963 0-204.25386667-91.62903703-204.25386667-204.25386667s91.62903703-204.25386667 204.25386667-204.25386667 204.25386667 91.62903703 204.25386666 204.25386667-91.7504 204.25386667-204.25386666 204.25386667z m0-330.83543704c-69.7837037 0-126.58157037 56.79786667-126.58157037 126.58157037s56.79786667 126.58157037 126.58157037 126.58157037 126.58157037-56.79786667 126.58157036-126.58157037-56.91922963-126.58157037-126.58157036-126.58157037z" p-id="3823"></path><path d="M925.60497778 984.95146667c-9.70903703 0-19.41807408-3.64088889-26.94257778-10.92266667L805.81973333 884.5842963c-15.4130963-14.92764445-15.89854815-39.44296297-0.9709037-54.85605927 14.92764445-15.4130963 39.44296297-15.89854815 54.85605926-0.9709037l92.84266666 89.4445037c15.4130963 14.92764445 15.89854815 39.44296297 0.9709037 54.85605927-7.5245037 8.00995555-17.71899259 11.89357037-27.91348147 11.89357037z" p-id="3824"></path></svg>',
    tip: '文章列表',
    className: 'details',
    tipPosition: 'n',
    click: () => getUserDetails(userDetailPages.value)
  },
  {
    hotkey: '⌥⌘I',
    name: 'importMarkdown',
    icon: '<svg t="1657593378315" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4733" width="32" height="32"><path d="M512.1 442.4c17.8 0 32.4 14.4 32.6 32v220l57.6-56.6c6.3-6.1 14.5-9.4 23.2-9.4s16.9 3.3 23.1 9.4c6.1 6 9.5 14.1 9.5 22.7s-3.4 16.6-9.5 22.7L535.2 794.5c-6.3 6.1-14.5 9.4-23.3 9.4-9.5 0-18.3-3.9-24.5-10.9l-0.1-0.1L375.4 683l-0.6-0.6c-5.9-6.1-9.1-14.1-9-22.6 0.1-8.4 3.5-16.3 9.6-22.2 6.3-6.1 14.5-9.4 23.2-9.4s16.9 3.3 23.1 9.4l57.4 56.9v-220c0.4-17.7 14.9-32 32.4-32l0.6-0.1zM228.6 788c-91 0-165-72.7-165-162 0-40.7 15.4-79.7 43.4-109.6 27.8-29.8 65.6-48.2 106.5-51.8l4.8-0.4-0.1-4.8c-1.5-50 25.9-109.1 73.4-158.1 59.9-61.8 140.2-97.2 220.3-97.2 150 0 276.8 110.2 295.1 256.3l0.6 4.5h5.8c36.2 0 73.2 17.2 101.4 47.2 29.4 31.3 45.7 71.7 45.7 114 0 87.7-71.3 159.3-159.9 161.9v-0.1H701c-18 0-32.6-14.3-32.6-32 0.2-17.6 14.7-32 32.4-32h94.9c54.9 0 99.6-43.9 99.6-97.9 0-54-44.7-97.9-99.6-97.9h-51.8v-31.7c0-125.7-104-227.9-231.7-227.9-127.8 0-231.7 102.2-231.7 227.9v32h-51.8c-54.9 0-99.6 43.9-99.6 97.9 0 54 44.7 97.9 99.6 97.9h95.1c17.6 0 32 14.3 32.2 32-0.2 17.6-14.7 32-32.4 32l-95-0.2z" fill="" p-id="4734"></path></svg>',
    tip: '导入Markdown',
    className: 'importMarkdown',
    tipPosition: 'n',
    click: () => uploadMarkdown()
  },
  {
    hotkey: '⌥⌘E',
    name: 'exportMarkdown',
    icon: '<svg t="1671687280575" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10093" width="32" height="32"><path d="M880.0256 143.9744l-98.7136 368.2304-56.1152-56.1152-30.72-30.72-40.3456 16.384c-105.472 42.8032-188.0064 92.9792-246.784 150.1184 4.5056-18.432 10.6496-36.6592 18.432-54.4768 32.1536-72.704 86.2208-125.1328 122.0608-159.744l2.2528-2.2528 47.7184-46.2848-47.104-47.104-39.3216-39.3216 368.64-98.7136M972.8 51.2l-587.5712 157.4912 119.6032 119.6032c-74.9568 72.4992-247.808 236.1344-132.7104 514.2528 0 0-60.416-191.2832 306.7904-339.968l136.3968 136.3968L972.8 51.2z" p-id="10094"></path><path d="M886.784 907.264H116.736V137.216h370.0736V71.68H51.2v901.12h901.12V537.1904h-65.536z" p-id="10095"></path></svg>',
    tip: '导出Markdown',
    className: 'exportMarkdown',
    tipPosition: 'n',
    click: () => exportMarkdown()
  },
  {
    hotkey: '⌥⌘P',
    name: 'publishDetail',
    icon: '<svg t="1657594080210" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6533" width="128" height="128"><path d="M879.7952 81.186133a21.3504 21.3504 0 0 0-21.649067 0.3584L143.607467 518.3488a21.333333 21.333333 0 0 0 1.9968 37.4784l229.000533 108.552533a21.333333 21.333333 0 1 0 18.2784-38.5536l-193.348267-91.648L797.909333 168.362667 462.429867 696.1408a20.189867 20.189867 0 0 0-3.328 11.306667l1.9968 215.68c0.110933 11.6992 9.634133 19.797333 21.333333 19.797333h0.196267c11.784533 0 21.248-8.430933 21.137066-20.215467l-1.732266-186.410666 351.581866 145.783466a21.3248 21.3248 0 0 0 19.933867-1.911466 21.333333 21.333333 0 0 0 9.5744-17.595734l7.4752-762.641066a21.3248 21.3248 0 0 0-10.8032-18.747734z m-365.909333 613.845334l333.354666-524.5952-6.4768 660.130133-326.877866-135.534933z" p-id="6534"></path></svg>',
    tip: '发布文章',
    className: 'publishDetail',
    tipPosition: 'n',
    click: () => save(1)
  },
  {
    hotkey: '⌥⌘S',
    name: 'tempSaveDetail',
    icon: '<svg t="1657595085932" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12954" width="128" height="128"><path d="M704 128l192 192v512a64 64 0 0 1-64 64H192a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h512z m-64 64H384v96h256V192z m64 26.496V352H320V192H192v640h128V512h384v320h128V346.496l-128-128zM640 832V576H384v256h256z" fill="#000000" fill-opacity=".9" p-id="12955"></path></svg>',
    tip: '保存文章',
    className: 'tempSaveDetail',
    tipPosition: 'n',
    click: () => save(0)
  }
];
/** 标签 */
const tags: Ref<string[]> = ref([]);
/** 专栏 */
const specials: Ref<string[]> = ref([]);
/** 表单 */
const publishEntity: Ref<DetailPublish> = ref({
  id: route.query.id ? Number(route.query.id) : 0,
  title: '',
  content: '',
  tags: '',
  tempSave: true,
  desc: '',
  special: '',
});
/** 监听获取 MD 文本 */
const vditorEditorChangeHandler = ({md}) => {
  publishEntity.value.content = md;
}
/** 监听专栏和标签的选项*/
const specialsChangeHandler = (val) => {
      publishEntity.value.special = val.join(',');
    },
    tagsChangeHandler = (val) => {
      publishEntity.value.tags = val.join(',');
    };

/** 保存文章 */
const save = async (mode: number) => {
  if (validateForm(mode)) {
    let tempEntity: DetailPublish = {
      id: 0,
      title: '',
      content: '',
      tags: '',
      tempSave: true,
      desc: '',
      special: '',
    };
    Object.assign(tempEntity, publishEntity.value);
    let content;
    try {
      // FIXME: 有文本加密异常的现象，不知道是否读取的文件被加过密的原因，先利用 try-catch 防止加密文本再次加密
      content = encrypt(decodeURIComponent(decrypt(publishEntity.value.content)));
    } catch (e) {
      content = encrypt(publishEntity.value.content);
    }
    tempEntity.content = content
    if (mode === 0) {
      // 暂存
      publishEntity.value.tempSave = true;
      tempEntity.tempSave = true;
    } else if (mode === 1) {
      // 发布
      publishEntity.value.tempSave = false;
      tempEntity.tempSave = false;
    }
    let res = await detailService.publishDetail(tempEntity);
    if (res && res.code === 0) {
      // 发布或暂存都会返回 id
      publishEntity.value.id = res.data;
      if (res.msg === '发布成功') {
        /*        operaMode.value = 4;
                operaConfirmationMsg.value = '已经发布成功了，是否开始新的文章？';
                submitOperaInfo.value = '是的,马上开启下一篇';
                cancelOperaInfo.value = '小改一手';
                operaConfirmationVisible.value = true;
                console.log(publishEntity.value)*/
        operaConfirmationSubmitHandler(4);
      }
    }
  }
}
/**
 * 验证表单
 * @param mode 判断发布还是暂存
 */
const validateForm = (mode: number) => {
  let form = publishEntity.value;
  let toastTitle = mode === 0 ? '暂存失败' : '发布失败';
  if (form.title.trim() === '' || form.title.trim().length < 3) {
    toast.error(toastTitle, '标题不能为空或者长度小于5。', 1500);
    return false;
  }
  if (form.tags.trim() === '' || form.tags.split(',').length < 1) {
    toast.error(toastTitle, '标签不能为空，请至少选择1个标签。', 1500);
    return false;
  }
  if (form.desc.trim() === '' || form.desc.trim().length < 5) {
    toast.error(toastTitle, '请至少用5个字简要描述下文章的内容。', 1500);
    return false;
  }
  return true;
}
/**
 * 确认保存数据
 */
const operaConfirmationVisible = ref(false), operaConfirmationMsg = ref(''), operaMode = ref(0);
const cancelOperaInfo = ref('我错了，我错了'), submitOperaInfo = ref('是的，不多BB');
const operaConfirmationObj: any = ref(null);


const refresh = () => {
  operaMode.value = 4;
  operaConfirmationMsg.value = '是否重置文章？';
  submitOperaInfo.value = '是的,我不干了';
  cancelOperaInfo.value = 'No no no~~';
  operaConfirmationVisible.value = true;
}
const operaConfirmationSubmitHandler = (mode: number) => {
      let tempSave;
      switch (mode) {
        case 0:
          saveDetail(1);
          break;
        case 1:
          deleteDetail(1);
          break;
        case 2:
          tempSave = validateForm(0);
          if (tempSave) {
            save(0);
          }
          break;
        case 3:
          // 上传 markdown 时清除原始数据
          // refresh();
          detailUpdateValues.content = publishEntity.value.content;
          for (let key in publishEntity.value) {
            if (key !== 'tempSave' && key !== 'id') {
              publishEntity.value[key] = '';
            }
          }
          detailUpdateValues.special = [];
          detailUpdateValues.tags = [];
          publishEntity.value.tempSave = true;
          // 利用延迟同步，清除 editor
          setTimeout(() => {
            detailUpdateValues.content = '';
          }, 50)
          /*          for (let key in publishEntity.value) {
                      if (key !== 'tempSave' && key !== 'id' && key !== 'content') {
                        publishEntity.value[key] = '';
                      }
                    }
                    detailUpdateValues.special = [];
                    detailUpdateValues.tags = [];
                    publishEntity.value.tempSave = true;
                    detailUpdateValues.content = '';*/
          break;
        case 4:
          operaConfirmationSubmitHandler(3);
          publishEntity.value.id = 0;
          break;
        default:
          operaConfirmationVisible.value = false;
      }
      // 上传 markdown 操作
      if (((mode === 2 && tempSave) || mode === 3) && operaConfirmationObj.value !== null) {
        markdownService.uploadFile(operaConfirmationObj.value).then(res => {
          detailUpdateValues.content = decodeURIComponent(decrypt(res));
        });
      }
      operaConfirmationVisible.value = false;
    },
    operaConfirmationCancelHandler = (mode: number) => {
      switch (mode) {
        case 2:
        case 3:
          markdownService.uploadFile(operaConfirmationObj.value).then(res => {
            detailUpdateValues.content = decodeURIComponent(decrypt(res));
          });
          operaConfirmationVisible.value = false;
          break;
        default:
          operaConfirmationVisible.value = false;
      }
    }
/** 获取用户文章 */
//TODO： 临时缓存，记录查询信息。【如果有记录时发生了发布、暂存或者删除等操作时，那么清除缓存。】
// 控制文章目录显隐
const detailSidebarVisible = ref(false),
    // 过滤筛选操作
    detailFilterInfo = reactive({
      // 文章
      title: '',
      // 是否发布
      published: null,
      // 个人专栏
      special: null,
      // 标签
      tags: null
    }),
    // 直接更新编辑器的文章内容
    detailUpdateValues = reactive({
      content: '',
      special: [] as string[],
      tags: [] as string[]
    })
// 监听筛选按钮
watch(() => [detailFilterInfo.published, detailFilterInfo.special, detailFilterInfo.tags], () => {
  tempDetails.value = [];
  userDetailPages.value.page = 1;
  nextTick(() => {
    detailSearch();
  })
}, {deep: true});

// 监听搜索框形成临时数据
let tempDetails: Ref<DetailResponseData[]> = ref([]),
    tempSaveDetailInfo = reactive({
      id: 0,
      tempSave: true
    });
watch(() => detailFilterInfo.title, (n) => {
  // 动态根据结果进行搜索
  if (tempDetails.value.length === 0) {
    // temp 为空时，将满数据进行存储
    tempDetails.value.push(...userDetails.value);
  }
  userDetails.value = tempDetails.value.filter(detail => detail.title && detail.title.indexOf(n) !== -1);
  if (n && n.trim() === '') {
    userDetails.value = tempDetails.value;
  }
});
// 临时保存文章信息
const saveTempDetailMsg = (id: number, tempSave: boolean) => {
  tempSaveDetailInfo.id = id;
  tempSaveDetailInfo.tempSave = !tempSave;
}, initTempDetailMsg = () => {
  tempSaveDetailInfo.id = 0;
  tempSaveDetailInfo.tempSave = true;
}
// 搜索用户文章
const detailSearch = async () => {
      // 普通搜索：文章标题关键字;例：测试数据
      // 专栏搜索：#专栏名称；例：#Java知识点
      // 专栏混合搜索：#专栏名称 文章关键字；例：#Java知识点 认识HashMap
      // 专栏作者搜索：#专栏名称$作者；例：#Java知识点$gzkemays
      userDetailLoad.value = true;
      userDetailPages.value.title = detailFilterInfo.title;
      if (detailFilterInfo.special) {
        userDetailPages.value.title = `#${detailFilterInfo.special} ${detailFilterInfo.title}`;
      }
      if (detailFilterInfo.tags) {
        userDetailPages.value.tags = detailFilterInfo.tags;
      } else {
        delete userDetailPages.value.tags;
      }
      if (detailFilterInfo.published !== null) {
        userDetailPages.value.tempSave = detailFilterInfo.published;
      } else {
        delete userDetailPages.value.tempSave;
      }
      await getUserDetails(userDetailPages.value, true);
    },
    // 编辑文章
    editDetail = async (id: number, tempSave: boolean) => {
      detailUpdateValues.tags = [];
      detailUpdateValues.special = [];
      let res = await detailService.getDetailById({id, tempSave});
      Object.assign(publishEntity.value, res.data);
      detailUpdateValues.content = decodeURIComponent(decrypt(res.data.content));
      if (res.data.special && res.data.special !== '') {
        detailUpdateValues.special = res.data.special.split(',');
      }
      if (res.data.tags && res.data.tags.trim() !== '') {
        detailUpdateValues.tags = res.data.tags.split(',');
      }
      detailSidebarVisible.value = false;
    },
    // 暂存或发布
    saveDetail = async (mode: number, id?: number, tempSave?: boolean) => {
      if (mode === 0) {
        operaMode.value = 0;
        cancelOperaInfo.value = tempSave ? '就点点,还没写完呢~' : '算了算了';
        submitOperaInfo.value = tempSave ? '我觉得灰常完美~发!' : '拉回来小改一波';
        if (id && tempSave !== undefined) {
          operaConfirmationVisible.value = true;
          saveTempDetailMsg(id, tempSave);
          operaConfirmationMsg.value = tempSave ? '是否确认发布?' : '该文章已经发布了，如果切换回暂存状态的话它的浏览量等数据就会清空哦~';
        } else {
          console.error('获取数据异常');
        }
      } else if (mode === 1 && tempSaveDetailInfo.id !== 0) {
        let res = await detailService.getDetailById(tempSaveDetailInfo);
        let tempDetail: DetailPublish = {
          id: 0,
          title: '',
          content: '',
          tags: '',
          tempSave: true,
          desc: '',
          special: '',
        };
        // 复制更新
        Object.assign(tempDetail, res.data);
        tempDetail.tempSave = tempSaveDetailInfo.tempSave;
        await detailService.publishDetail(tempDetail);
        operaConfirmationVisible.value = false;
        // 还原初始数据
        initTempDetailMsg();
        await detailSearch();
      }
    },
    // 删除文章
    deleteDetail = async (mode: number, id?: number, tempSave?: boolean) => {
      if (mode === 0) {
        operaMode.value = 1;
        cancelOperaInfo.value = '删?为什么要删!';
        submitOperaInfo.value = '走吧走吧~~';
        if (id && tempSave !== undefined) {
          operaConfirmationVisible.value = true;
          saveTempDetailMsg(id, tempSave);
          operaConfirmationMsg.value = tempSave ? '是否确认删除?' : '删除后文章的浏览量等数据就会清空哦~';
          operaConfirmationMsg.value += '30天冷静期之后后悔了的话可以去【个人主页--回收站】处找回哦~';
        } else {
          console.error('获取数据异常');
        }
      } else if (mode === 1 && tempSaveDetailInfo.id !== 0) {
        await detailService.deleteDetail({id: tempSaveDetailInfo.id});
        operaConfirmationVisible.value = false;
        // 还原初始数据
        initTempDetailMsg();
        await detailSearch();
      }
    }
// 用户文章列表 value
let userDetails: Ref<DetailResponseData[]> = ref([]);
// 用户文章选择
let userDetailSelected = ref(null), userDetailsLoading = ref(false), userDetailLoad = ref(true);
// 用户文章列表分页
let userDetailPages: Ref<DetailPageInfo> = ref({
  page: 1,
  limit: 10,
  delete: false
});
// 获取用户的文章列表
const getUserDetails = async (info: DetailPageInfo, refresh?: boolean) => {
  // 清空临时的 details
  tempDetails.value = [];
  detailSidebarVisible.value = true;
  if (userDetailLoad.value) {
    userDetailsLoading.value = true;
    let res: ResponseResult<DetailResponseData[]> = await detailService.getUserDetails(info).finally(() => {
      userDetailsLoading.value = false
    });
    if (res.data.length <= 0 && !refresh) {
      // 判断获取数据后是否有数据，如果没有的话，再判断 page 是否等于 1，true 为 1 false -1
      if (info.page) {
        info.page = info.page === 1 ? 1 : info.page - 1;
      }
      await nextTick(() => {
        userDetailLoad.value = false;
        if (!userDetailLoad.value) {
          toast.error('提示提示~', '没有文章啦~憋找了。');
        }
      });
    } else {
      userDetails.value.push(...res.data);
    }
    if (refresh) {
      userDetails.value = res.data;
    }
  }
}
const userDetailRef = ref(null);
// table 滚动监听
/** 页面滚动操作 */
let scrollHandlerInfo: ScrollHandlerInfo = {
      doc: document.getElementsByClassName('p-sidebar-content')[0],
      otherJudgements: {
        and: true,
        judgements: userDetailLoad.value
      },
      func: () => {
        userDetailPages.value.page += 1;
        getUserDetails(userDetailPages.value);
      }
    },
    handleScroll = () => scrollHandler(scrollHandlerInfo);
watch(detailSidebarVisible, (n) => {
  // 监听滑动加载
  nextTick(() => {
    let doc = document.getElementsByClassName('p-sidebar-content')[0];
    if (doc) {
      scrollHandlerInfo.doc = doc;
      if (n) {
        doc.addEventListener('scroll', handleScroll, true);
      } else {
        doc.removeEventListener('scroll', handleScroll, true);
      }
    }
  })
})
/** 返回主页面 */
const toHome = () => {
  router.push({
    path: '/',
  });
};
/** 上传 markdown */
let mdStatus = 0;
const uploadMarkdown = () => {
      let inputObj = document.createElement('input')
      inputObj.setAttribute('id', '_ef');
      inputObj.setAttribute('type', 'file');
      inputObj.setAttribute('style', 'visibility:hidden');
      inputObj.setAttribute('accept', '.md');
      document.body.appendChild(inputObj);
      inputObj.click();
      inputObj.addEventListener('change', (e: any) => {
        if (e?.target) {
          let files;
          if (e.target?.files && (files = e.target.files).length > 0) {
            operaConfirmationObj.value = files[0];
            uploadPreHandler(mdStatus);
          }
        }
      })
    },
    // 导出 markdown
    exportMarkdown = () => {
      let blob = new Blob([publishEntity.value.content], {
        type: 'text/plain'
      });
      const a = document.createElement("a");
      const url = window.URL.createObjectURL(blob);
      let title = publishEntity.value.title;
      if (title === undefined || title.trim() === '') {
        title = '未命名.md'
      } else {
        title += '.md';
      }
      const filename = title;
      a.href = url;
      a.download = filename;
      a.click();
      window.URL.revokeObjectURL(url);
    },
    // 上传前操作
    uploadPreHandler = (status: number) => {
      if (status === 0) {
        // status 为 0 时为默认操作
        let entity = publishEntity.value;
        if (publishEntity.value.content.trim() !== '') {
          operaConfirmationMsg.value = '是否要暂存当前在编辑的文章内容？';
          cancelOperaInfo.value = '不要了';
          submitOperaInfo.value = '存起来再说';
          status++;
          operaConfirmationVisible.value = true;
          uploadPreHandler(status);
        } else {
          for (let key in entity) {
            if (entity[key] && entity[key] !== '') {
              operaConfirmationVisible.value = true;
              operaConfirmationMsg.value = '检测到已编辑的标题等数据，是否继续保留？【注意：如果是编辑已有的文章会修改原来文章的内容。】';
              cancelOperaInfo.value = '保留吧';
              submitOperaInfo.value = '清除数据';
              status = 2;
              uploadPreHandler(status);
            }
          }
        }
      } else if (status === 1) {
        // 暂存操作
        operaMode.value = 2;
        mdStatus = 0;
      } else if (status === 2) {
        // 清除或保存数据操作
        operaMode.value = 3;
        mdStatus = 0;
      }
    }
/** 获取默认数据 */
const defaultInitData = () => {
  // 获取标签
  tagService.getAllTags().then(res => {
    let data;
    if ((data = res?.data)) {
      tags.value = data as string[];
    }
  });
  // 获取专栏
  specialService.getSpecialList().then(res => {
    let data;
    if ((data = res?.data)) {
      specials.value = data.map(dta => dta.name);
    }
  });
};


/** 监听页面按钮事件 */
document.onkeydown = function (e) {
  let keyboardEvent: KeyboardEvent = e;
  // 保存组合键
  if (keyboardEvent.ctrlKey && keyboardEvent.code === 'KeyS') {
    (window.event as Event).preventDefault();
  }
  if (keyboardEvent.shiftKey && keyboardEvent.code === 'Tab') {
    (window.event as Event).preventDefault();
  }
}

onMounted(() => {
  defaultInitData();
});
</script>

<style lang="less">
#editor {
  .vditor-reset {
    padding: 10px !important;
  }
}


.p-sidebar-close {
  position: absolute !important;
  top: 5px;
}

.m-table-th {
  text-align: center !important;

  .p-column-header-content {
    display: block !important;
  }
}
</style>